package com.iot.service.mqtt.handler;

import com.iot.service.mqtt.config.Constant;
import com.iot.service.mqtt.model.request.TlMqttPubRecReq;
import com.iot.service.mqtt.model.request.TlMqttPubRelReq;
import com.iot.service.mqtt.model.variable.TlMqttPubRecVariableHead;
import com.iot.service.mqtt.retry.RetryStrategy;
import com.iot.service.mqtt.retry.TlRetryMessage;
import com.iot.service.mqtt.service.pub.IPublishStoreService;
import com.iot.service.mqtt.service.rel.IPubrelStoreService;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.AttributeKey;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


/**
 * @Author: hszhou
 * @Date: 2024/12/5 9:46
 * @Description: rec消息处理器
 */
@ChannelHandler.Sharable
@Component
@RequiredArgsConstructor
public class TlMqttPubRecHandler extends SimpleChannelInboundHandler<TlMqttPubRecReq> {

    private static final Logger logger = LoggerFactory.getLogger(TlMqttPubRecHandler.class);

    private final IPublishStoreService publishStoreService;

    private final IPubrelStoreService pubrelStoreService;

    private final RetryStrategy retryStrategy;
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TlMqttPubRecReq req) throws Exception {
        logger.debug("in【PUBREC】 handler");
        String clientId = ctx.channel().attr(AttributeKey.valueOf(Constant.CLIENT_ID)).get().toString();
        TlMqttPubRecVariableHead vh = req.getVariableHead();
        Long messageId = vh.getMessageId();

        //收到rec的消息 说明接受方已经收到了发送放的publish消息了 可以吧这个publish消息删除了 并且删除session中的pub消息
        publishStoreService.clearPublishMessage(clientId,messageId).subscribe(e-> logger.info("删除【{}】的消息【{}】",clientId,messageId));
        logger.debug("【CLIENT】 2. 【{}】 remove pub messageId【{}】",clientId,messageId);
        //发送REL消息 告诉发送方 可以发送COMP消息了
        TlMqttPubRelReq res = TlMqttPubRelReq.build(messageId);
        //保存rel的消息 是为了cleansession为0的时候 将这个数据发生给客户端
        pubrelStoreService.savePubRelMessage(clientId,messageId,res)
                .subscribe(e->{
                    logger.info("保存Rel【{}】的消息【{}】",clientId,messageId);
                    if (e){

                        //定时任务发送rel消息 收到comp后取消
                        retryStrategy.retry(new TlRetryMessage(messageId,res),clientId);
                        logger.debug("【CLIENT】 3. 【{}】 save pubrec message 【{}】",clientId,messageId);
                        ctx.channel().writeAndFlush(res);
                        logger.debug("client【{}】 build 【PUBREL】",clientId);
                    }
                });



    }
}
